import res.nero_network as neural_network
import res.aigame_config as config
import random
import copy


class Genome(object):
    # 每一个个体基因当中所携带的基因数据(神经网络的数据)
    def __init__(self, network_data, score):
        self.data = network_data  # 存放基因数据
        self.score = score  # 用分数来区分个体的优异


class Generation(object):  # 世代
    def __init__(self):
        self.genomes = []   # 基因列表

    def add_genome(self, genome):  # 利用循环将优秀个体插入到世代当中
        for temp in self.genomes:
            if genome.score > temp.score:
                index = self.genomes.index(temp)
                self.genomes.insert(index, genome)
                return
            self.genomes.append(genome)

    def creat_next_generation(self):   # 生成下一代
        network_data_list = []
        # 1.选取精英个体直接遗传
        for i in range(round(config.population*config.elite)):
            network_data_list.append(self.genomes[i].data)
        # 2. 选取一部分随机个体
        for i in range(round(config.population*config.new_born)):
            network = neural_network.NuralNetwork(config.network[0], config.network[1], config.network[2],)
            network_data_list.append(network.getNetwork())
        # 3. 选取两个个体进行繁殖
        while True:
            if len(network_data_list) == config.population:
                break
            father = self.genomes[random.randint(0, round(config.population/2))]
            mother = self.genomes[random.randint(round(config.population/2), config.population-1)]
            child = self.breed(father,mother)
            network_data_list.append(child.data)
        return network_data_list

    def breed(self, father, mother):
        child = copy.deepcopy(father)
        # 交叉
        for i in range(len(child.data['weights'])):
            if random.randint() < 0.5:
                child.data['weights'][i] = mother.data['weights'][i]
        # 变异
        for i in range(len(child.data['weights'])):
            if random.randint() < config.variation:
                child.data['weights'][i] = neural_network.random_weight()


class GenerationManager(object):
    def __init__(self):
        self.generations = []  # 世代列表

    def creat_generation(self):  # 从世代中选出优秀个体来创建下一代
        if len(self.generations) == 0:
            network_data_list = self.__first_generation()
        else:
            network_data_list = self.__next_generation()
        self.generations.append(Generation())
        return network_data_list

    def __first_generation(self):
        '''
        创建第一个世代
        :return: 世代中所有个体中的基因数据
        '''
        net_work_data_list = []
        for i in range(config.population):    # 随机 创建30个个体的神经网络数据
            network = neural_network.NuralNetwork(config.network[0], config.network[1], config.network[2])
            net_work_data_list.append(network.getNetwork())
        return net_work_data_list

    def __next_generation(self):
        '''
        下一个世代
        :return: 下一个世代中的所有个体的基因数据
        '''
        network_data_list = self.generations[-1].create_next_generation()  # 利用上一代的数据取优生成下一代
        return network_data_list

    def add_genome(self, genome):
        self.generations[-1].add_genome(genome)


if __name__ == '__main__':
    manager = GenerationManager()
    manager.creat_generation()
    for genome in manager.generations[-1].genomes:
        print("1")
        print(genome.data)